package com.qumitech.visualnovel.service.wallet.imp;

import com.alibaba.fastjson.JSONObject;
import com.qumitech.visualnovel.component.exception.BusinessException;
import com.qumitech.visualnovel.component.util.ExcelUtils;
import com.qumitech.visualnovel.component.util.FileUtil;
import com.qumitech.visualnovel.component.util.HttpInvokeUtil;
import com.qumitech.visualnovel.component.util.TimeUtils;
import com.qumitech.visualnovel.model.common.BaseRsp;
import com.qumitech.visualnovel.model.common.ResultEnum;
import com.qumitech.visualnovel.controller.vo.withdraw.WithdrawAdminQueryDTO;
import com.qumitech.visualnovel.controller.vo.withdraw.WithdrawVo;
import com.qumitech.visualnovel.model.dao.console.UserInfo;
import com.qumitech.visualnovel.model.common.UrlConstant;
import com.qumitech.visualnovel.pubdef.dto.wallet.WithdrawApplyAdminDTO;
import com.qumitech.visualnovel.pubdef.dto.wallet.WithdrawApplyCollectDTO;
import com.qumitech.visualnovel.pubdef.dto.wallet.WithdrawApplyCollectImportDTO;
import com.qumitech.visualnovel.pubdef.dto.wallet.WithdrawApplyImportDTO;
import com.qumitech.visualnovel.pubdef.pubenum.WithdrawStateEnum;
import com.qumitech.visualnovel.service.exception.ExceptionService;
import com.qumitech.visualnovel.service.wallet.WalletService;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


/**
 * WalletService 实现
 *
 * @author ZhChNing
 * @date Created in 2019/1/28 17:38
 */

@Service
public class WalletServiceImpl implements WalletService {

    private final String wallet = "/wallet/console/withdraw";
    private final String updateWallet = "/wallet/console/withdraw/audit";
    private final String collectWallet = "/wallet/console/withdraw/collect";

    private final String reTryWithDrawUrl = "/retry/deal_withdraw";
    private final String rootUrl = "/wallet/console/withdraw/";

    @Autowired
    private ExceptionService exceptionService;

    public Map<String, Object> getUrl(String url, WithdrawAdminQueryDTO queryDTO) {
        Map<String, String> paramMap = new HashMap<>(16);
        if (queryDTO.getOffset() != null) {
            paramMap.put("offset", queryDTO.getOffset().toString());
        }

        if (queryDTO.getLimit() != null) {
            paramMap.put("limit", queryDTO.getLimit().toString());
        }

        if (queryDTO.getStartTime() != null) {
            paramMap.put("startTime", queryDTO.getStartTime());
        }

        if (queryDTO.getEndTime() != null) {
            paramMap.put("endTime", queryDTO.getEndTime());
        }

        if (queryDTO.getState() != null) {
            paramMap.put("state", queryDTO.getState().toString());
        }

        if (queryDTO.getUid() != null) {
            paramMap.put("uid", queryDTO.getUid());
        }

        if (queryDTO.getWithdrawId() != null) {
            paramMap.put("withdraw_id", queryDTO.getWithdrawId());
        }

        if (queryDTO.getWalletType() != null) {
            paramMap.put("wallet_type", queryDTO.getWalletType().toString());
        }

        if (queryDTO.getPayType() != null) {
            paramMap.put("pay_type", queryDTO.getPayType().toString());
        }

        if (queryDTO.getOrderBy() != null) {
            paramMap.put("order_by_field", queryDTO.getOrderBy());
        }

        if (queryDTO.getOrderType() != null) {
            paramMap.put("sql_order_by", queryDTO.getOrderType());
        }

        if (queryDTO.getUserState() != null) {
            paramMap.put("user_state", queryDTO.getUserState());
        }

        String body = HttpInvokeUtil.httpGet(url, paramMap, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        if (rsp == null || rsp.getStatus() != ResultEnum.SUCCESS.getState()
                || rsp.getData() == null) {
            throw new BusinessException(ResultEnum.FAILURE);
        }
        return (Map<String, Object>) rsp.getData();
    }

    @Override
    public Map<String, Object> listWallet(WithdrawAdminQueryDTO queryDTO) {
        String url = UrlConstant.SERVER_URL + wallet;
        return getUrl(url, queryDTO);
    }

    @Override
    public Map<String, Object> withdrawCollect(WithdrawAdminQueryDTO queryDTO) {
        String url = UrlConstant.SERVER_URL + collectWallet;
        return getUrl(url, queryDTO);
    }

    @Override
    public void updateWithdrawState(WithdrawVo withdrawVo) {
        String url = UrlConstant.SERVER_URL + updateWallet;
        withdrawVo.setOperator(getOperatorName());
        String req = JSONObject.toJSONString(withdrawVo);
        String body = HttpInvokeUtil.httpPostJson(url, req, UrlConstant.DefaultEncode, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        if (rsp == null || rsp.getStatus() != ResultEnum.SUCCESS.getState()) {
            throw new BusinessException(ResultEnum.WALLET_WITHDRAW_AUDIT_ERROR);
        }
    }

    @Override
    public Map<String, Object> exportMultipartFile(WithdrawAdminQueryDTO queryDTO, HttpServletResponse request) {
        Map<String, Object> rspMap = listWallet(queryDTO);
        WithdrawApplyImportDTO importDTO = JSONObject.parseObject(JSONObject.toJSONString(rspMap),
                WithdrawApplyImportDTO.class);
        Map<String, Object> resultMap = new HashMap<>(16);
        try {
            List<WithdrawApplyAdminDTO> amounts = importDTO.getWithdrawApplyAdminDTOS();
            amounts.stream().forEach(withdrawApplyAdminDTO -> {
                withdrawApplyAdminDTO.setAmountF(String.format("%.4f",
                        (float) withdrawApplyAdminDTO.getAmount() / 10000));
                withdrawApplyAdminDTO.setRealAmountF(String.format("%.4f",
                        (float) withdrawApplyAdminDTO.getRealAmount() / 10000));
                withdrawApplyAdminDTO.setStates(WithdrawStateEnum.getWithdrawStateEnum(
                        withdrawApplyAdminDTO.getState()).desc());
                withdrawApplyAdminDTO.setCreateTimeString(TimeUtils.getTime(withdrawApplyAdminDTO.getCreateTime()));
                if (withdrawApplyAdminDTO.getWalletType() != null) {
                    if (withdrawApplyAdminDTO.getWalletType().intValue() == 1) {
                        withdrawApplyAdminDTO.setWalletName("钻石收益提现");
                    }
                    if (withdrawApplyAdminDTO.getWalletType().intValue() == 2) {
                        withdrawApplyAdminDTO.setWalletName("红包提现");
                    }
                }
            });

            ExcelUtils<WithdrawApplyAdminDTO> xls = new ExcelUtils<>(WithdrawApplyAdminDTO.class);
            String filename = FileUtil.getExcelName();
            request.reset();
            request.setContentType("application/vnd.ms-excel;charset=utf-8");

            request.setHeader("Content-Disposition", "attachment;filename=" + filename);
            OutputStream outputStream = request.getOutputStream();
            xls.exportExcel("提现账单导出", amounts, outputStream);
            outputStream.flush();
            outputStream.close();
            resultMap.put("title", filename);
            return resultMap;
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        throw new BusinessException(ResultEnum.EXCEL_EXPORT_ERROR);
    }

    @Override
    public Map<String, Object> exportMultipartCollectFile(WithdrawAdminQueryDTO queryDTO, HttpServletResponse request) {
        Map<String, Object> rspMap = withdrawCollect(queryDTO);
        WithdrawApplyCollectImportDTO importDTO = JSONObject.parseObject(JSONObject.toJSONString(rspMap),
                WithdrawApplyCollectImportDTO.class);
        Map<String, Object> resultMap = new HashMap<>(16);
        try {

            List<WithdrawApplyCollectDTO> amounts = importDTO.getWithdrawApplyAdminDTOS();

            amounts.stream().forEach(applyCollectDTO -> {
                applyCollectDTO.setSumAmountF(String.format("%.4f", (float) applyCollectDTO.getSumAmount() / 10000));
                applyCollectDTO.setRealAmountF(String.format("%.4f", (float) applyCollectDTO.getRealAmount() / 10000));
            });

            ExcelUtils<WithdrawApplyCollectDTO> xls = new ExcelUtils<>(WithdrawApplyCollectDTO.class);
            String filename = FileUtil.getExcelName();
            request.reset();
            request.setContentType("application/vnd.ms-excel;charset=utf-8");
            request.setHeader("Content-Disposition", "attachment;filename=" + filename);
            OutputStream outputStream = request.getOutputStream();
            xls.exportExcel("提现汇总导出", amounts, outputStream);
            outputStream.flush();
            outputStream.close();
            resultMap.put("title", filename);
            return resultMap;
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        throw new BusinessException(ResultEnum.EXCEL_EXPORT_ERROR);
    }

    @Override
    public void retryDealWithdraw(String withdrawId) {
        String url = UrlConstant.SERVER_URL + rootUrl + withdrawId + reTryWithDrawUrl;
        String body = HttpInvokeUtil.httpPostJson(url, withdrawId, UrlConstant.DefaultEncode, null);
        BaseRsp rsp = JSONObject.parseObject(body, BaseRsp.class);
        exceptionService.getFailureResultEnum(rsp);
    }

    private String getOperatorName() {
        Subject subject = SecurityUtils.getSubject();
        UserInfo activeUser = (UserInfo) subject.getPrincipal();
        return activeUser.getUsername();
    }
}
